#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using log4net;
using xConnected.Core.Interfaces.Service;
using xConnected.Core.Model;
using xConnected.Core.Model.ViewModel.xConnected.Core.Model.ViewModel;
using xConnected.Service;

#endregion

namespace xConnected.Controllers
{
    public class MessageController : BaseController<Message>
    {
        protected IMessageService MessageService;
        protected ExpertProfileService _expertProfileService;
        protected CompanyListService _companyListService;
        protected CompanyProfileService _companyProfileService;
        protected ExpertListService _expertListService;
        protected MessageCompanyUserService _messageCompanyUserService;
        protected MessageExpertUserService _messageExpertUserService;
        protected MessageFolderService _messageFolderService;
        protected MessagePositionUserService _messagePositionUserService;
        protected PositionListService _positionListService;
        protected PositionService _Positionservice;
        protected UserService _userService;

        public MessageController(IMessageService MessageService, ExpertProfileService ExpertProfileService,
                                 CompanyProfileService companyProfileService, PositionService Positionservice,
                                 UserService userService, MessageExpertUserService messageExpertUserService,
                                 MessageCompanyUserService messageCompanyUserService,
                                 MessagePositionUserService messagePositionUserService,
                                 MessageFolderService messageFolderService,
                                 ExpertListService expertListService, CompanyListService companyListService,
                                 PositionListService positionListService)
        {
            base.Service = this.MessageService = MessageService;
            _expertProfileService = ExpertProfileService;
            _companyProfileService = companyProfileService;
            _Positionservice = Positionservice;
            _userService = userService;
            _messageExpertUserService = messageExpertUserService;
            _messageCompanyUserService = messageCompanyUserService;
            _messagePositionUserService = messagePositionUserService;
            _messageFolderService = messageFolderService;
            _expertListService = expertListService;
            _companyListService = companyListService;
            _positionListService = positionListService;
        }

        [HttpPost]
        public JsonResult Save(Message message)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                if (message.ParentId == 0)
                {
                    message.ParentId = null;
                }

                IList<MessageExpertUser> messageExpertUsers = new List<MessageExpertUser>();
                IList<MessageCompanyUser> messageCompanyUsers = new List<MessageCompanyUser>();
                IList<MessagePositionUser> messagePositionUsers = new List<MessagePositionUser>();
                if (message.MessageExpertUsers != null)
                {
                    message.MessageExpertUsers.ToList().ForEach(m => messageExpertUsers.Add(m));
                    message.MessageExpertUsers.Clear();
                }
                if (message.MessageCompanyUsers != null)
                {
                    message.MessageCompanyUsers.ToList().ForEach(m => messageCompanyUsers.Add(m));
                    message.MessageCompanyUsers.Clear();
                }
                if (message.MessagePositionUsers != null)
                {
                    message.MessagePositionUsers.ToList().ForEach(m => messagePositionUsers.Add(m));
                    message.MessagePositionUsers.Clear();
                }


                MessageService.SaveOrUpdate(message);

                if (messageExpertUsers.Count != 0)
                {
                    foreach (var messageExpertUser in messageExpertUsers)
                    {
                        messageExpertUser.Message = message;
                        var user = _expertProfileService.GetById(messageExpertUser.ExpertProfileId).User;
                        messageExpertUser.MessageFolder = messageExpertUser.IsSender
                                                              ? user.MessageFolders.FirstOrDefault(
                                                                  m => m.FolderType == 1)
                                                              : user.MessageFolders.FirstOrDefault(
                                                                  m => m.FolderType == 0);
                        _messageExpertUserService.SaveOrUpdate(messageExpertUser);
                    }
                }
                if (messageCompanyUsers.Count != 0)
                {
                    foreach (var messageCompanyUser in messageCompanyUsers)
                    {
                        messageCompanyUser.Message = message;
                        var user = _companyProfileService.GetById(messageCompanyUser.CompanyProfileId).User;
                        messageCompanyUser.MessageFolder = messageCompanyUser.IsSender
                                                               ? user.MessageFolders.FirstOrDefault(
                                                                   m => m.FolderType == 1)
                                                               : user.MessageFolders.FirstOrDefault(
                                                                   m => m.FolderType == 0);
                        _messageCompanyUserService.SaveOrUpdate(messageCompanyUser);
                    }
                }
                if (messagePositionUsers.Count != 0)
                {
                    foreach (var messagePositionUser in messagePositionUsers)
                    {
                        messagePositionUser.Message = message;
                        var user = _Positionservice.GetById(messagePositionUser.PositionId).CompanyProfile.User;
                        messagePositionUser.MessageFolder = messagePositionUser.IsSender
                                                               ? user.MessageFolders.FirstOrDefault(
                                                                   m => m.FolderType == 1)
                                                               : user.MessageFolders.FirstOrDefault(
                                                                   m => m.FolderType == 0);
                        _messagePositionUserService.SaveOrUpdate(messagePositionUser);
                    }
                }
                message.MessageExpertUsers = messageExpertUsers;
                message.MessageCompanyUsers = messageCompanyUsers;
                message.MessagePositionUsers = messagePositionUsers;
                MessageService.SaveOrUpdate(message);
                return Json(message.Id, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult SetAsRead(MessageUser messageUser)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
                
                if (messageUser.MessageExpertUserIds != null)
                {
                    foreach (var messageExpertUserId in messageUser.MessageExpertUserIds)
                    {
                        var messageExpertUser = _messageExpertUserService.GetById(messageExpertUserId);
                        //if messageuser belongs to current user set as read=true
                        if(messageExpertUser.MessageFolder.OwnerId == userId)
                        {
                            messageExpertUser.IsRead = true;
                            _messageExpertUserService.SaveOrUpdate(messageExpertUser);
                        }
                    }
                }
                if (messageUser.MessageCompanyUserIds != null)
                {
                    foreach (var messageCompanyUserId in messageUser.MessageCompanyUserIds)
                    {
                        var messageCompanyUser = _messageCompanyUserService.GetById(messageCompanyUserId);
                        //if messageuser belongs to current user set as read=true
                        if (messageCompanyUser.MessageFolder.OwnerId == userId)
                        {
                            messageCompanyUser.IsRead = true;
                            _messageCompanyUserService.SaveOrUpdate(messageCompanyUser);
                        }
                    }
                }
                if (messageUser.MessagePositionUserIds != null)
                {
                    foreach (var messagePositionUserId in messageUser.MessagePositionUserIds)
                    {
                        var messagePositionUser = _messagePositionUserService.GetById(messagePositionUserId);
                        //if messageuser belongs to current user set as read=true
                        if (messagePositionUser.MessageFolder.OwnerId == userId)
                        {
                            messagePositionUser.IsRead = true;
                            _messagePositionUserService.SaveOrUpdate(messagePositionUser);
                        }
                    }
                }
                return Json("Ok", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new { Result = "ERROR", ex.Message }, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult GetRecipientsAutocomplete(string searchTerm, int maxRows)
        {
            //this lists of ids are set like this just so we can have same type for var Members 
            //and we can make union of recipients which are profiles and lists
            var expertsIds = _expertProfileService.GetAll().Select(p => p.Id).Take(3).ToList();
            var companiesIds = _companyProfileService.GetAll().Select(p => p.Id).Take(3).ToList();
            var PositionsIds = _Positionservice.GetAll().Select(p => p.Id).Take(3).ToList();
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
                var expertLists =
                    _expertListService.GetAll().ToList().OrderBy(el => el.Name).Where(el => el.OwnerId == userId).Select
                        (el => new
                                   {
                                       Title = el.Name + " <Expert List>",
                                       el.Id,
                                       Type = "ppList",
                                       Members = el.ExpertProfiles.Select(ep => ep.Id).ToList()
                                   });
                var expertProfiles =
                    _expertProfileService.GetAll().ToList().OrderBy(ep => ep.Title).Where(
                        ep => ep.ExpertLists.Any(el => expertLists.Select(t => t.Id).Contains(el.Id))).Select(p => new
                                                                                                                     {
                                                                                                                         Title = p.Title + " <Expert Profile>",
                                                                                                                         Id = p.Id,
                                                                                                                         Type = "pp",
                                                                                                                         Members = expertsIds
                                                                                                                     });
                var companyLists =
                    _companyListService.GetAll().ToList().OrderBy(cl => cl.Name).Where(cl => cl.OwnerId == userId).
                        Select(cl => new
                                         {
                                             Title = cl.Name + " <Company List>",
                                             Id = cl.Id,
                                             Type = "cpList",
                                             Members = cl.CompanyProfiles.Select(cp => cp.Id).ToList()
                                         });
                var companyProfiles =
                    _companyProfileService.GetAll().ToList().OrderBy(cp => cp.Title).Where(
                        cp => cp.CompanyLists.Any(cl => companyLists.Select(t => t.Id).Contains(cl.Id))).Select(c => new
                                                                                                                       {
                                                                                                                           Title = c.Title + " <Company Profile>",
                                                                                                                           Id = c.Id,
                                                                                                                           Type = "cp",
                                                                                                                           Members = companiesIds
                                                                                                                       });
                var positionLists =
                    _positionListService.GetAll().ToList().OrderBy(pl => pl.Name).Where(pl => pl.OwnerId == userId).
                        Select(pl => new
                                         {
                                             Title = pl.Name + " <Position List>",
                                             Id = pl.Id,
                                             Type = "prList",
                                             Members = pl.Positions.Select(p => p.Id).ToList()
                                         });
                var positionProfiles =
                    _Positionservice.GetAll().ToList().OrderBy(p => p.Title).Where(
                        p => p.PositionLists.Any(pl => positionLists.Select(t => t.Id).Contains(pl.Id))).Select(p => new
                                                                                    {
                                                                                        Title = p.Title + " <Position/Project Profile>",
                                                                                        Id = p.Id,
                                                                                        Type = "pr",
                                                                                        Members = PositionsIds
                                                                                    });


                var recipients =
                    expertLists.Union(companyLists).Union(positionLists).Union(expertProfiles).Union(companyProfiles).Union(positionProfiles);

                if (searchTerm != "")
                {
                    recipients = recipients.Where(p => p.Title.ToLower().Contains(searchTerm.ToLower())).Take(maxRows);
                }

                return Json(recipients, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult GetSenderAutocomplete(string searchTerm, int maxRows)
        {
            var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var ExpertProfiles =
                    _expertProfileService.GetAll().Where(p => p.UserId == userId).OrderBy(p => p.Title).Select(
                        p => new
                                 {
                                     p.Title,
                                     p.Id,
                                     Type = "pp"
                                 });
                var companyProfiles =
                    _companyProfileService.GetAll().Where(c => c.UserId == userId).OrderBy(c => c.Title).Select(c => new
                                                                                                                         {
                                                                                                                             c
                                                                                                                         .
                                                                                                                         Title,
                                                                                                                             c
                                                                                                                         .
                                                                                                                         Id,
                                                                                                                             Type
                                                                                                                         =
                                                                                                                         "cp"
                                                                                                                         });
                var positionProfiles =
                    _Positionservice.GetAll().Where(p => p.CompanyProfile.UserId == userId).OrderBy(p => p.Title).Select(
                        p => new
                                 {
                                     p.Title,
                                     p.Id,
                                     Type = "pr"
                                 });

                var senders = ExpertProfiles.Union(companyProfiles).Union(positionProfiles);

                if (searchTerm != "")
                {
                    senders = senders.Where(p => p.Title.ToLower().Contains(searchTerm.ToLower())).Take(maxRows);
                }

                return Json(senders, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult GetSender()
        {
            var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var ExpertProfiles = _expertProfileService.GetAll().Where(p => p.UserId == userId).Select(p => new
                                                                                                                   {
                                                                                                                       p
                                                                                                                   .
                                                                                                                   IsDefault,
                                                                                                                       p
                                                                                                                   .
                                                                                                                   Title,
                                                                                                                       p
                                                                                                                   .Id,
                                                                                                                       p
                                                                                                                   .
                                                                                                                   Created,
                                                                                                                       p
                                                                                                                   .
                                                                                                                   Description,
                                                                                                                       p
                                                                                                                   .
                                                                                                                   Photo,
                                                                                                                       Type
                                                                                                                   =
                                                                                                                   "pp"
                                                                                                                   });
                var companyProfiles = _companyProfileService.GetAll().Where(c => c.UserId == userId).Select(c => new
                                                                                                                     {
                                                                                                                         c
                                                                                                                     .
                                                                                                                     IsDefault,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Title,
                                                                                                                         c
                                                                                                                     .Id,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Created,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Description,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Photo,
                                                                                                                         Type
                                                                                                                     =
                                                                                                                     "cp"
                                                                                                                     });
                var positionProfiles =
                    _Positionservice.GetAll().Where(pr => pr.CompanyProfile.UserId == userId).Select(pr => new
                                                                                                              {
                                                                                                                  pr.
                                                                                                              IsDefault,
                                                                                                                  pr.
                                                                                                              Title,
                                                                                                                  pr.Id,
                                                                                                                  pr.
                                                                                                              Created,
                                                                                                                  pr.
                                                                                                              Description,
                                                                                                                  pr.
                                                                                                              Photo,
                                                                                                                  Type =
                                                                                                              "pr"
                                                                                                              });

                var sender = ExpertProfiles.Union(companyProfiles).Union(positionProfiles).Where(s => s.IsDefault);

                return Json(sender, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult MoveToTrash(MessageUser messageUser)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
                if (messageUser.MessageExpertUserIds != null)
                {
                    foreach (var messageExpertUserId in messageUser.MessageExpertUserIds)
                    {
                        var messageExpertUser = _messageExpertUserService.GetById(messageExpertUserId);
                        messageExpertUser.MessageFolder =
                            _messageFolderService.GetAll().First(m => m.OwnerId == userId && m.FolderType == 2);
                        _messageExpertUserService.SaveOrUpdate(messageExpertUser);
                    }
                }
                if (messageUser.MessageCompanyUserIds != null)
                {
                    foreach (var messageCompanyUserId in messageUser.MessageCompanyUserIds)
                    {
                        var messageCompanyUser = _messageCompanyUserService.GetById(messageCompanyUserId);
                        messageCompanyUser.MessageFolder =
                            _messageFolderService.GetAll().First(m => m.OwnerId == userId && m.FolderType == 2);
                        _messageCompanyUserService.SaveOrUpdate(messageCompanyUser);
                    }
                }
                if (messageUser.MessagePositionUserIds != null)
                {
                    foreach (var messagePositionUserId in messageUser.MessagePositionUserIds)
                    {
                        var messagePositionUser = _messagePositionUserService.GetById(messagePositionUserId);
                        messagePositionUser.MessageFolder =
                            _messageFolderService.GetAll().First(m => m.OwnerId == userId && m.FolderType == 2);
                        _messagePositionUserService.SaveOrUpdate(messagePositionUser);
                    }
                }

                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult MoveToFolder(MessageUser messageUser)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
                if (messageUser.MessageExpertUserIds != null)
                {
                    foreach (var messageExpertUserId in messageUser.MessageExpertUserIds)
                    {
                        var messageExpertUser = _messageExpertUserService.GetById(messageExpertUserId);
                        messageExpertUser.MessageFolder =
                            _messageFolderService.GetAll().First(
                                m => m.OwnerId == userId && m.Name == messageUser.FolderName);
                        _messageExpertUserService.SaveOrUpdate(messageExpertUser);
                    }
                }
                if (messageUser.MessageCompanyUserIds != null)
                {
                    foreach (var messageCompanyUserId in messageUser.MessageCompanyUserIds)
                    {
                        var messageCompanyUser = _messageCompanyUserService.GetById(messageCompanyUserId);
                        messageCompanyUser.MessageFolder =
                            _messageFolderService.GetAll().First(
                                m => m.OwnerId == userId && m.Name == messageUser.FolderName);
                        _messageCompanyUserService.SaveOrUpdate(messageCompanyUser);
                    }
                }
                if (messageUser.MessagePositionUserIds != null)
                {
                    foreach (var messagePositionUserId in messageUser.MessagePositionUserIds)
                    {
                        var messagePositionUser = _messagePositionUserService.GetById(messagePositionUserId);
                        messagePositionUser.MessageFolder =
                            _messageFolderService.GetAll().First(
                                m => m.OwnerId == userId && m.Name == messageUser.FolderName);
                        _messagePositionUserService.SaveOrUpdate(messagePositionUser);
                    }
                }

                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult DeleteMessage(MessageUser messageUser)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var userId = _userService.GetUserByUsername(User.Identity.Name).Id;
                if (messageUser.MessageExpertUserIds != null)
                {
                    foreach (var messageExpertUserId in messageUser.MessageExpertUserIds)
                    {
                        var messageExpertUser = _messageExpertUserService.GetById(messageExpertUserId);
                        //if it comes from trash folder
                        if (messageExpertUser.MessageFolder.FolderType == 2)
                        {
                            messageExpertUser.IsDeleted = true;
                            _messageExpertUserService.SaveOrUpdate(messageExpertUser);
                            var message = messageExpertUser.Message;
                            var messageUsers =
                                message.MessageExpertUsers.Select(m => m.IsDeleted).Union(
                                    message.MessageCompanyUsers.Select(m => m.IsDeleted)).Union(
                                        message.MessagePositionUsers.Select(m => m.IsDeleted));
                            var delete = messageUsers.All(m => m);
                            if (delete)
                            {
                                MessageService.Delete(message);
                            }
                        }
                    }
                }
                if (messageUser.MessageCompanyUserIds != null)
                {
                    foreach (var messageCompanyUserId in messageUser.MessageCompanyUserIds)
                    {
                        var messageCompanyUser = _messageCompanyUserService.GetById(messageCompanyUserId);
                        //if it comes from trash folder
                        if (messageCompanyUser.MessageFolder.FolderType == 2)
                        {
                            messageCompanyUser.IsDeleted = true;
                            _messageCompanyUserService.SaveOrUpdate(messageCompanyUser);
                            var message = messageCompanyUser.Message;
                            var messageUsers =
                                message.MessageExpertUsers.Select(m => m.IsDeleted).Union(
                                    message.MessageCompanyUsers.Select(m => m.IsDeleted)).Union(
                                        message.MessagePositionUsers.Select(m => m.IsDeleted));
                            var delete = messageUsers.All(m => m);
                            if (delete)
                            {
                                MessageService.Delete(message);
                            }
                        }
                    }
                }
                if (messageUser.MessagePositionUserIds != null)
                {
                    foreach (var messagePositionUserId in messageUser.MessagePositionUserIds)
                    {
                        var messagePositionUser = _messagePositionUserService.GetById(messagePositionUserId);
                        //if it comes from trash folder
                        if (messagePositionUser.MessageFolder.FolderType == 2)
                        {
                            messagePositionUser.IsDeleted = true;
                            _messagePositionUserService.SaveOrUpdate(messagePositionUser);
                            var message = messagePositionUser.Message;
                            var messageUsers =
                                message.MessageExpertUsers.Select(m => m.IsDeleted).Union(
                                    message.MessageCompanyUsers.Select(m => m.IsDeleted)).Union(
                                        message.MessagePositionUsers.Select(m => m.IsDeleted));
                            var delete = messageUsers.All(m => m);
                            if (delete)
                            {
                                MessageService.Delete(message);
                            }
                        }
                    }
                }

                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }
    }
}